#include <stdlib.h>

#include "fsl_debug_console.h"

#include "mytask.h"
#include "audio.h"
#include "endpoint.h"
#include "ring_buf.h"
#include "kws.h"
#include "mfcc.h"
/* 优先级宏定义 */
#define VAD_THREAD_PRIO 		(osPriorityNormal + 2)	/* 端点检测线程优先级 */
#define SAVE_THREAD_PRIO		(osPriorityNormal + 1)	/* 数据存储线程优先级 */
#define KWS_THREAD_PRIO			(osPriorityNormal + 3) 	/* 音频识别线程优先级 */

char output_class[12][8] = {"Silence", "Unknown","yes","no","up","down","left","right","on","off","stop","go"};

/* 用于触发端点检测任务（valid_audio_detection）的信号量 */
Semaphore xSemaphore_vad(0);
/* 用于触发端点检测任务（valid_audio_detection）的信号量 */
Semaphore xSemaphore_save(0);

/* 数据缓存完成后，用于出发识别任务 */
static Semaphore xSemaphore_kws(0);
/* 环形缓冲结构体 */
static RING_BUF ring_buf_str;
/* 端点检测结构体 */
static EP_DETECT_STR vad_str;

static sai_transfer_t xfer;
static Thread kws_thread(KWS_THREAD_PRIO);
static Thread data_save_thread(SAVE_THREAD_PRIO);
static Thread valid_audio_detect_thread(VAD_THREAD_PRIO);


void valid_audio_detection_thread(void)
{
	uint32_t res_vad;
	xfer.dataSize = BUFFER_SIZE_BYTES;
	while (1)
	{
		xSemaphore_vad.wait();
		xfer.data = rx_buf + flag_audio_buf * BUFFER_SIZE_BYTES;
		if(kStatus_Success == SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer))
		{
		}
		/* 对采集到的一帧数据做预处理，取单声道数据 */
		audio_data_pre_deal((int16_t *)(rx_buf + flag_audio_buf * BUFFER_SIZE_BYTES));
		/* 将预处理后的音频数据存入环形缓冲 */
		ring_buf_input(&ring_buf_str, pre_deal_buf);
		/* 做端点检测 */
		res_vad = start_endpoint_detection(&vad_str, pre_deal_buf);
		PRINTF("%d\r\n", res_vad);
		/* 检测到起始点，将环形缓冲器数据存入audio_buf，并唤醒音频数据缓存任务，挂起端点检测任务 */
		if (res_vad == GET_START_POINT)
		{
			ring_buf_output(&ring_buf_str, audio_buf); // 将缓冲区数据存入audio_buf
			start_point_flag = 1;
		}

	}
}

void valid_data_save_thread(void)
{
	uint32_t i = NUM_RING_BUF_FRAMES;
	uint32_t res_vad;
	xfer.dataSize = BUFFER_SIZE_BYTES;
	while(1)
	{
		xSemaphore_save.wait();
		xfer.data = rx_buf + flag_audio_buf * BUFFER_SIZE_BYTES;
		if(kStatus_Success == SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer))
		{
		}
		audio_data_pre_deal((int16_t *)(rx_buf + flag_audio_buf * BUFFER_SIZE_BYTES));
		if (i >= AUDIO_BUF_MAX_NUM_FRAMES)
		{
			memcpy(audio_buf + i * NUM_FRAM_SAMPLE, pre_deal_buf, sizeof(int16_t) * NUM_FRAM_SAMPLE);
			i = NUM_RING_BUF_FRAMES;
			/* 发送识别任务信号量，触发识别任务 */
			xSemaphore_kws.release();
			start_point_flag = 0;
		} else {
			memcpy(audio_buf + i * NUM_FRAM_SAMPLE, pre_deal_buf, sizeof(int16_t) * NUM_FRAM_SAMPLE);
			i ++;
			res_vad = start_endpoint_detection(&vad_str, pre_deal_buf);
			if (res_vad == GET_END_POINT)
			{
				i = NUM_RING_BUF_FRAMES;
				/* 发送识别任务信号量，触发识别任务 */
				start_point_flag = 0;
				xSemaphore_kws.release();
			}
		}		
	}
}

void key_words_spotting_thread(void)
{
	int i;
	while(1)
	{
		xSemaphore_kws.wait();
		/* 执行ds cnn网络对数据做识别，返回结果编号 */
		i = kws_using_ds_cnn(audio_buf);
		/*
		* 在此处添加后处理，获取连续识别结果
		*/
		PRINTF("%s\r\n", output_class[i]);
	}
}

int32_t all_task_init(void)
{
	/* 初始化环形缓冲器 */
	ring_buf_init(&ring_buf_str);
	
	/* 初始化相关任务 */
	if (valid_audio_detect_thread.start(valid_audio_detection_thread) != osOK)
	{
		PRINTF("valid_audio_detection_thread creation failed!.\r\n");
		return -1;
	}
	if(data_save_thread.start(valid_data_save_thread) != osOK)
	{
		PRINTF("valid_data_save_thread creation failed!.\r\n");
		return -1;
	}	
	if (kws_thread.start(key_words_spotting_thread) != osOK)
	{
		PRINTF("key_words_spotting_thread creation failed!.\r\n");
		return -1;
	}
	return 0;
}

